/*****************************************************************************
 * Copyright (C) 2003-2005 Jean-Daniel Fekete and INRIA, France              *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the X11 Software License    *
 * a copy of which has been included with this distribution in the           *
 * license-infovis.txt file.                                                 *
 *****************************************************************************/

import java.io.*;
import java.util.*;
import java.util.Map.Entry;

import com.sun.javadoc.*;

/**
 * Class FactoryPropertiesGenerator
 * 
 * @author Jean-Daniel Fekete
 * @version $Revision: 1.7 $
 */
public class FactoryPropertiesGenerator {
    static TreeMap factories = new TreeMap();

    public static boolean start(RootDoc root) {
        String tagName = "infovis.factory";
        manageContents(root.classes(), tagName);
        generateProperties();
        //generateJava();
        return true;
    }

    private static void generateProperties() {
        for (Iterator fiter = factories.keySet().iterator(); fiter
                .hasNext();) {
            String factoryName = (String) fiter.next();
            String propName = factoryName.toLowerCase() + ".properties";
            TreeMap factoryMap = (TreeMap) factories.get(factoryName);
            try {
                int index = 0;
                FileWriter rout = new FileWriter("src/resources/"
                        + propName);
                BufferedWriter out = new BufferedWriter(rout);
                PrintWriter pout = new PrintWriter(out);
                pout.println("# This file is automatically generated DO NOT MODIFY!");

                for (Iterator iter = factoryMap.keySet().iterator(); iter
                        .hasNext();) {
                    String name = (String) iter.next();
                    String[] params = (String[]) factoryMap.get(name);
                    pout.println("name." + index + ":" + name);
                    pout.println("class." + index + ":" + params[0]);
                    for (int i = 2; i < params.length; i++) {
                        pout.println("data" + (i-1) + "." + index + ":"
                                + params[i]);
                    }
                    pout.println();
                    index++;
                }
                pout.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    
    private static void generateJava() {
        try {
            FileWriter rout = new FileWriter("src/infovis/InitFactories.java");
            BufferedWriter out = new BufferedWriter(rout);
            PrintWriter pout = new PrintWriter(out);
            pout.println("// This file is automatically generated DO NOT MODIFY!");
            pout.println("package infovis;");
            pout.println();
            pout.println("import infovis.column.ColumnFactory;");
            pout.println("import infovis.metadata.AggregationFactory;");
            pout.println("import infovis.column.ColumnFactory;");
            pout.println("import infovis.graph.io.GraphReaderFactory;");
            pout.println("import infovis.graph.io.GraphWriterFactory;");
            pout.println("import infovis.graph.visualization.layout.GraphLayoutFactory;");
            pout.println("import infovis.metadata.AggregationFactory;");
            pout.println("import infovis.panel.ControlPanelFactory;");
            pout.println("import infovis.panel.render.VisualPanelFactory;");
            pout.println("import infovis.table.io.TableReaderFactory;");
            pout.println("import infovis.tree.io.TreeReaderFactory;");
            pout.println("import infovis.tree.visualization.nodelink.TreeLayoutFactory;");
            pout.println("import infovis.tree.visualization.treemap.TreemapFactory;");
            pout.println("import infovis.visualization.VisualizationFactory;");
            pout.println("import infovis.visualization.inter.InteractorFactory;");
            pout.println("import infovis.visualization.inter.RendererInteractorFactory;");
            pout.println("import infovis.visualization.linkShapers.LinkShaperFactory;");
            pout.println("import infovis.visualization.render.ItemRendererFactory;");      
            pout.println("");
            pout.println("public class InitFactories {");
            pout.println("\tpublic static void init() {");
            StringBuffer buf = new StringBuffer();
            for (Iterator fiter = factories.entrySet().iterator(); 
                    fiter.hasNext();) {
                Entry e = (Entry)fiter.next();
                String factoryName = (String)e.getKey(); 
                TreeMap factoryMap = (TreeMap) e.getValue();
                for (Iterator iter = factoryMap.entrySet().iterator(); 
                    iter.hasNext();) {
                    Entry e2 = (Entry)iter.next();
                    String name = (String) e2.getKey();
                    String[] params = (String[]) e2.getValue();
                    buf.setLength(0);
                    buf.append("\t");
                    buf.append(factoryName);
                    buf.append(".getInstance().add(");
                    buf.append('"');
                    buf.append(name);
                    buf.append('"');
                    buf.append(",");
                    buf.append('"');
                    buf.append(params[0]);
                    buf.append('"');
                    buf.append(",");
                    if (params.length > 2) {
                        buf.append('"');
                        buf.append(params[2]);
                        buf.append('"');
                    }
                    else {
                        buf.append("null");
                    }
                    buf.append(");\n");
                    pout.print(buf.toString());
                }
            }
            pout.println("\t}");
            pout.println("}");
            pout.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static String[] parseLine(String text) {
        StringReader sin = new StringReader(text);
        StreamTokenizer stok = new StreamTokenizer(sin);
        stok.resetSyntax();
	stok.wordChars('!', '/');
	stok.wordChars('0', '9');
	stok.wordChars(':', '@');
        stok.wordChars('A', 'Z');
	stok.wordChars('[', '`');
        stok.wordChars('a', 'z');
        stok.wordChars('{', '~');
        stok.wordChars(131, 255);
        stok.whitespaceChars(0, ' ');
        stok.quoteChar('"');
        ArrayList al = new ArrayList();

        try {
            for (int tok = stok.nextToken(); tok != StreamTokenizer.TT_EOF; tok = stok
                    .nextToken()) {
                al.add(stok.sval);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        String[] params = new String[al.size()];
        al.toArray(params);
        System.err.print("params=");
        for (int i = 0; i < params.length; i++) {
            System.err.print("\"" + params[i] + "\" ");
        }
        System.err.print("\n");
        return params;
    }

    private static void manageContents(ClassDoc[] classes,
            String tagName) {
        for (int i = 0; i < classes.length; i++) {
            Tag[] tags = classes[i].tags(tagName);
            if (tags.length > 0) {
                for (int k = 0; k < tags.length; k++) {
                    String text = tags[k].text();
                    String[] params = parseLine(text);
                    if (params.length == 0) {
                        System.err
                                .println("Not enough arguments in @infovis.factory tag for "
                                        + classes[i].qualifiedName());
                        continue;
                    }
                    String factoryName = params[0];

                    TreeMap factoryMap = (TreeMap) factories
                            .get(factoryName);
                    if (factoryMap == null) {
                        factoryMap = new TreeMap();
                        factories.put(factoryName, factoryMap);
                    }
                    params[0] = classes[i].qualifiedName();
                    // 0=class name, 1=name, 2... extra params
                    if (params.length > 1) {
                        factoryMap.put(params[1], params);
                    }
                }
            }
        }
    }
}